今天要弄懂:
const [user, setUser] = useState(null)
這一行在幹嘛?
我們先從會員登入這件事情開始。
假設一開始還沒登入。
我們可以先用:
null
表示「目前沒有會員」。
所以:
useState(null)
裡面的 null,今天先理解成:
會員登入狀態一開始是空的,也就是還沒有人登入。
如果 Anthony 登入成功,之後我們希望 user 變成:
{
name: 'Anthony'
}
所以整件事情其實就是:
一開始
null
↓ 登入成功
後來
{ name: 'Anthony' }
我們現在需要一個地方,把「目前是哪一個狀態」記住。
這就是 useState 在這裡要幫我們做的事情。
useState(null)先把左邊全部遮住:
useState(null)
這裡其實有兩件不同的東西:
useState
→ React 提供的 Hook
→ 「state」的概念是從這裡進來的
null
→ 傳給 useState 的初始值
→ 表示一開始還沒有會員登入
所以:
useState(null)
不是「null 就是 state」。
比較準確的讀法是:
React,我要用
useState管理一份 state;這份 state 一開始的值是null。
換句話說:
state 是什麼?
→ React 幫 Component 記住、而且更新後會影響畫面的資料
那 null 是什麼?
→ 這份 state 的初始值
會員登入狀態就很符合。
因為它可能從:
未登入
變成:
已登入
而畫面也會跟著不同。
例如:
未登入
→ 顯示 Sign In
已登入
→ 顯示 Hello, Anthony
[user, setUser] 是什麼?再看完整一點:
const [user, setUser] = useState(null)
呼叫 useState(null) 之後,React 會回傳兩個東西。
可以先想成:
第一個
→ 目前這份 state 的值
第二個
→ 更新這份 state 的 function
放到會員系統就是:
user
→ 目前的 state 值
→ 現在登入的是誰
setUser
→ 更新這份 state 的 function
→ 之後要修改登入狀態時使用
所以這一整行可以拆成:
const [user, setUser] = useState(null)
useState
→ 告訴 React:我要管理一份 state
null
→ 這份 state 的初始值
user
→ 目前拿到的 state 值
setUser
→ 更新這份 state 的 function
所以:
const [user, setUser] = useState(null)
現在可以先翻成中文:
React,請幫我記住會員登入狀態。
一開始沒有人登入,所以是 null。
現在的登入資料叫 user。
以後要改它,就用 setUser。
這樣就已經比整句硬背容易很多了。
[]?這個 [] 不是 React 特殊語法。
它是 JavaScript 的 Array 解構。
useState(null) 可以先想成 React 回傳兩個東西:
[
目前的值,
修改它的 function
]
user 和 setUser 是 React 規定的名字嗎?不是。
我們自己取的。
例如可以寫:
const [member, changeMember] = useState(null)
只是 React 很常用這種命名方式:
user
setUser
count
setCount
isOpen
setIsOpen
所以看到:
const [user, setUser] = useState(null)
可以先找規律:
資料:user
修改資料:setUser
一開始:
const [user, setUser] = useState(null)
所以:
user
→ null
假設登入成功後,我拿到:
{
name: 'Anthony'
}
這時候可以:
setUser({
name: 'Anthony'
})
先不要想太多。
今天只需要知道:
setUser(...)
↓
把 user 更新成新的會員資料
於是概念上就變成:
原本
user = null
↓ setUser({ name: 'Anthony' })
後來
user = { name: 'Anthony' }
這就是會員系統裡 useState 最實際的用途。
const user = null?如果寫:
const user = null
它當然可以代表「目前沒登入」。
但登入之後,我們不能再做:
user = {
name: 'Anthony'
}
因為 const 不能重新賦值。
那換成 let 呢?
let user = null
JavaScript 的確允許:
user = {
name: 'Anthony'
}
可是這裡又出現 React 的需求。
我們不只想把資料改掉。
我們還希望:
user 改了
↓
畫面也重新看一次 user
↓
決定現在要顯示什麼
所以 React 才不是只叫我們放一個普通的 let user。
而是:
const [user, setUser] = useState(null)
用 setUser 更新時,React 會知道:
這個資料改了,畫面可能也要更新。
先理解到這裡就夠了。
const?這一行看起來很奇怪:
const [user, setUser] = useState(null)
剛剛明明才說 user 之後會變。
為什麼還是 const?
因為我們不是這樣改:
user = {
name: 'Anthony'
}
而是:
setUser({
name: 'Anthony'
})
也就是說:
我們沒有直接重新指定這一次的 user,而是請 React 更新它記住的會員狀態。
所以這裡可以繼續用 const。
現在先只看這段:
import { useState } from 'react'
function App() {
const [user, setUser] = useState(null)
function login() {
setUser({
name: 'Anthony'
})
}
return (
<div>
<p>
{user ? `Hello, ${user.name}` : '尚未登入'}
</p>
<button onClick={login}>
Sign In
</button>
</div>
)
}
先拆成兩部分。
第一部分:
const [user, setUser] = useState(null)
負責:
記住目前登入狀態
第二部分:
{user ? `Hello, ${user.name}` : '尚未登入'}
負責:
看 user 現在有沒有資料
↓
決定畫面顯示什麼
所以如果:
user = null
畫面就是:
尚未登入
如果 user 之後變成:
{
name: 'Anthony'
}
畫面就可以變成:
Hello, Anthony
onClick 部分現在才輪到按鈕。
我們希望:
按下 Sign In
↓
setUser(...)
↓
user 變成 Anthony
可以先寫成:
<button
onClick={() => {
setUser({
name: 'Anthony'
})
}}
>
Sign In
</button>
今天先不要研究:
() => {}
也不要研究 event。
只把:
onClick={...}
理解成:
使用者按下按鈕時,再執行裡面的程式。
所以整個流程就是:
一開始
user = null
畫面:尚未登入
↓ 按 Sign In
setUser({
name: 'Anthony'
})
↓
user 變成 Anthony
畫面:Hello, Anthony
這就是今天真正想看到的結果。
前面沒有先講 render。
因為如果一開始就看到:
state 更新
→ re-render
→ state preservation
我其實還是不知道畫面到底發生什麼事。
現在用會員登入看,就比較有畫面了。
React 原本用:
user = null
算出:
尚未登入
按下 Sign In 後,user 更新。
React 再用新的:
user = { name: 'Anthony' }
重新算一次現在應該顯示什麼。
變成:
Hello, Anthony
render:React 執行 Component、計算這次畫面應該長什麼樣子。
所以目前可以先記成:
render
≈ React 根據現在的資料,算一次畫面要長怎樣
這個詞聽起來很可怕。
但現在其實也可以用會員登入理解。
按下 Sign In 之後:
user = Anthony
React 為了更新畫面,會再執行一次 Component。
可是它沒有忘記 user,重新變回:
null
而是還記得:
{ name: 'Anthony' }
這件事情就是我們之後會碰到的 state preservation。
今天先把它翻成白話:
React 重新算畫面時,還記得之前的 state。
const [user, setUser] = useState(null)
現在可以拆成:
useState
→ React 提供的 Hook
→ 真正把「state」這個機制帶進來的地方
null
→ state 的初始值
→ 一開始還沒登入
user
→ 目前這份 state 的值
→ 現在的會員資料
setUser
→ 更新這份 state 的 function
[]
→ JavaScript Array 解構
→ 把 useState 回傳的兩個東西分別取出來
然後:
setUser({
name: 'Anthony'
})
就是:
把登入狀態更新成 Anthony
好累Q_Q 每天都在跟時間賽跑欸...有了孩子之後一下子就快12點了...我想在學校真的是最幸福的事情。(中年男子的哀傷?